#include <unity.h>
#include "qpcpp.hpp"
#include "bsp.h"
#include "auth_ao.h"
#include "db_ao.h"
#include "ui_ao.h"
#include "auth_events.h"

// Global AO instances (defined in their respective implementation files)
extern UiAo* const the_AO_Ui;
extern AuthAo* const the_AO_Auth;
extern DbAo* const the_AO_Db;

// Test result flags
static bool login_success_event = false;
static bool login_failure_event = false;

// Event handlers for test results
static void onLoginSuccess(QP::QEvt const* /*e*/) {
    login_success_event = true;
}

static void onLoginFailure(QP::QEvt const* /*e*/) {
    login_failure_event = true;
}

// Test Active Object to receive events
class TestAo : public QP::QActive {
public:
    TestAo() : QActive(initial) {}
    
protected:
    Q_STATE_DECL(initial) {
        Q_UNUSED_PAR(e);
        
        // Subscribe to authentication response events
        subscribe(LOGIN_RESPONSE_SUCCESS_SIG);
        subscribe(LOGIN_RESPONSE_FAILURE_SIG);
        
        return tran(&processing);
    }
    
    Q_STATE_DECL(processing) {
        QP::QState status_;
        switch (e->sig) {
            case LOGIN_RESPONSE_SUCCESS_SIG: {
                onLoginSuccess(e);
                status_ = Q_RET_HANDLED;
                break;
            }
            case LOGIN_RESPONSE_FAILURE_SIG: {
                onLoginFailure(e);
                status_ = Q_RET_HANDLED;
                break;
            }
            default: {
                status_ = super(&top);
                break;
            }
        }
        return status_;
    }
};

// Global pointers for testing
static TestAo* testAo = nullptr;

void setUp(void)
{
    // This is run before EACH test
    // Create and start test AO
    testAo = new TestAo();
    static QP::QEvtPtr testQueueSto[10];
    testAo->start(
        1U,                  // QP priority (highest)
        testQueueSto,        // event queue storage
        Q_DIM(testQueueSto), // queue length [events]
        nullptr, 0U);        // no stack storage
    
    // Reset test result flags
    login_success_event = false;
    login_failure_event = false;
}

void tearDown(void)
{
    // This is run after EACH test
    // Clean up allocated memory
    delete testAo;
}

// Test that AO instances are created
void test_ao_instances(void)
{
    TEST_ASSERT_NOT_NULL(the_AO_Ui);
    TEST_ASSERT_NOT_NULL(the_AO_Auth);
    TEST_ASSERT_NOT_NULL(the_AO_Db);
}

int main(void)
{
    UNITY_BEGIN();
    RUN_TEST(test_ao_instances);
    return UNITY_END();
}